package agent.action;

import java.util.ArrayList;
import java.util.Random;

import agent.memory.MemoryA;
import settings.Settings;
import driver.Move;

public class RandomNumberTrail_A {
	
	int side, ID, length, counter;
	int [][] numberSpread;
	
	Random generator;
	
	ArrayList < Move > possibleCells;
	
	public MemoryA brain;
	
	public RandomNumberTrail_A( MemoryA brain, int ID ) {
		
		this.side = Settings.side;
		this.ID = ID;
		
		this.brain = brain;
		
		generator =  new Random();
	}
	
	public Move stepTowardsZero( int xInitial, int yInitial ) {
		
		Move trail = findNewTrails( xInitial, yInitial );
		
		return tracePathBack( trail );
	}
	
	private Move findNewTrails( int startX, int startY ) {
		
		int xNow, yNow, choice;
		
		counter = 1;
		
		possibleCells = new ArrayList < Move > ();
		Move current = new Move( ID, startX, startY );
		possibleCells.add( current );
		
		numberSpread = new int [ side ][ side ];
		numberSpread[ startY ][ startX ] = counter;
		
		while( possibleCells.isEmpty() == false ) {
			
			counter++;
			length = possibleCells.size();
			
			for( int i = 0; i < length; i++ ) {
				
				xNow = possibleCells.get( 0 ).getXLoc();
				yNow = possibleCells.get( 0 ).getYLoc();
				
				choice = generator.nextInt( 4 ) + 1;
				
				switch( choice ) {
				
				case 1:
					
					try {
						
						if( ( brain.memHits[ yNow ][ xNow - 1 ] > -1 ) && ( brain.memHits[ yNow ][ xNow - 1 ] < 10000 ) && ( numberSpread[ yNow ][ xNow - 1 ] == 0 ) ) {
							
							numberSpread[ yNow ][ xNow - 1 ] = counter;
							current = new Move( ID, xNow - 1, yNow );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow ][ xNow - 1 ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					try {
						
						if( ( brain.memHits[ yNow + 1 ][ xNow ] > -1 ) && ( brain.memHits[ yNow + 1 ][ xNow ] < 10000 ) && ( numberSpread[ yNow + 1 ][ xNow ] == 0 ) ) {
							
							numberSpread[ yNow + 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow + 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow + 1 ][ xNow ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					try {
						
						if( ( brain.memHits[ yNow ][ xNow + 1 ] > -1 ) && ( brain.memHits[ yNow ][ xNow + 1 ] < 10000 ) && ( numberSpread[ yNow ][ xNow + 1 ] == 0 ) ) {
							
							numberSpread[ yNow + 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow + 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow ][ xNow + 1 ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}

					try {
						
						if( ( brain.memHits[ yNow - 1 ][ xNow ] > -1 ) && ( brain.memHits[ yNow - 1 ][ xNow ] < 10000 ) && ( numberSpread[ yNow - 1 ][ xNow ] == 0 ) ) {
							
							numberSpread[ yNow - 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow - 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow - 1 ][ xNow ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					break;
					
				case 2:
					
					try {
						
						if( ( brain.memHits[ yNow + 1 ][ xNow ] > -1 ) && ( brain.memHits[ yNow + 1 ][ xNow ] < 10000 ) && ( numberSpread[ yNow + 1 ][ xNow ] == 0 ) ) {
							
							numberSpread[ yNow + 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow + 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow + 1 ][ xNow ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					try {
						
						if( ( brain.memHits[ yNow ][ xNow + 1 ] > -1 ) && ( brain.memHits[ yNow ][ xNow + 1 ] < 10000 ) && ( numberSpread[ yNow ][ xNow + 1 ] == 0 ) ) {
							
							numberSpread[ yNow + 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow + 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow ][ xNow + 1 ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}

					try {
						
						if( ( brain.memHits[ yNow - 1 ][ xNow ] > -1 ) && ( brain.memHits[ yNow - 1 ][ xNow ] < 10000 ) && ( numberSpread[ yNow - 1 ][ xNow ] == 0 ) ) {
							
							numberSpread[ yNow - 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow - 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow - 1 ][ xNow ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					try {
						
						if( ( brain.memHits[ yNow ][ xNow - 1 ] > -1 ) && ( brain.memHits[ yNow ][ xNow - 1 ] < 10000 ) && ( numberSpread[ yNow ][ xNow - 1 ] == 0 ) ) {
							
							numberSpread[ yNow ][ xNow - 1 ] = counter;
							current = new Move( ID, xNow - 1, yNow );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow ][ xNow - 1 ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					break;
					
				case 3:
					
					try {
						
						if( ( brain.memHits[ yNow ][ xNow + 1 ] > -1 ) && ( brain.memHits[ yNow ][ xNow + 1 ] < 10000 ) && ( numberSpread[ yNow ][ xNow + 1 ] == 0 ) ) {
							
							numberSpread[ yNow + 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow + 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow ][ xNow + 1 ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}

					try {
						
						if( ( brain.memHits[ yNow - 1 ][ xNow ] > -1 ) && ( brain.memHits[ yNow - 1 ][ xNow ] < 10000 ) && ( numberSpread[ yNow - 1 ][ xNow ] == 0 ) ) {
							
							numberSpread[ yNow - 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow - 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow - 1 ][ xNow ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					try {
						
						if( ( brain.memHits[ yNow ][ xNow - 1 ] > -1 ) && ( brain.memHits[ yNow ][ xNow - 1 ] < 10000 ) && ( numberSpread[ yNow ][ xNow - 1 ] == 0 ) ) {
							
							numberSpread[ yNow ][ xNow - 1 ] = counter;
							current = new Move( ID, xNow - 1, yNow );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow ][ xNow - 1 ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					try {
						
						if( ( brain.memHits[ yNow + 1 ][ xNow ] > -1 ) && ( brain.memHits[ yNow + 1 ][ xNow ] < 10000 ) && ( numberSpread[ yNow + 1 ][ xNow ] == 0 ) ) {
							
							numberSpread[ yNow + 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow + 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow + 1 ][ xNow ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					break;
					
				case 4:
					
					try {
						
						if( ( brain.memHits[ yNow - 1 ][ xNow ] > -1 ) && ( brain.memHits[ yNow - 1 ][ xNow ] < 10000 ) && ( numberSpread[ yNow - 1 ][ xNow ] == 0 ) ) {
							
							numberSpread[ yNow - 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow - 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow - 1 ][ xNow ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					try {
						
						if( ( brain.memHits[ yNow ][ xNow - 1 ] > -1 ) && ( brain.memHits[ yNow ][ xNow - 1 ] < 10000 ) && ( numberSpread[ yNow ][ xNow - 1 ] == 0 ) ) {
							
							numberSpread[ yNow ][ xNow - 1 ] = counter;
							current = new Move( ID, xNow - 1, yNow );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow ][ xNow - 1 ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					try {
						
						if( ( brain.memHits[ yNow + 1 ][ xNow ] > -1 ) && ( brain.memHits[ yNow + 1 ][ xNow ] < 10000 ) && ( numberSpread[ yNow + 1 ][ xNow ] == 0 ) ) {
							
							numberSpread[ yNow + 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow + 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow + 1 ][ xNow ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					try {
						
						if( ( brain.memHits[ yNow ][ xNow + 1 ] > -1 ) && ( brain.memHits[ yNow ][ xNow + 1 ] < 10000 ) && ( numberSpread[ yNow ][ xNow + 1 ] == 0 ) ) {
							
							numberSpread[ yNow + 1 ][ xNow ] = counter;
							current = new Move( ID, xNow, yNow + 1 );
							possibleCells.add( current );
							
							if( brain.memHits[ yNow ][ xNow + 1 ] == 0 ) {
								
								return current;
							}
						}
					}
					
					catch( ArrayIndexOutOfBoundsException e ) {		
					}
					
					break;
					
				default:	
					break;
				}
						
				possibleCells.remove( 0 );
			}
		}
		
		return null;
	}
	
	private Move tracePathBack( Move destination ) {
		
		int nextX, nextY;
		
		nextX = destination.getXLoc();
		nextY = destination.getYLoc();
		
		while( numberSpread[ nextY ][ nextX ] != 2 ) {
			
			counter--;
			
			try {
				
				if( numberSpread[ nextY ][ nextX - 1 ] == counter ) {
					
					nextX--;
					continue;
				}
			}
			
			catch( ArrayIndexOutOfBoundsException e ) {
			}
			
			try {
				
				if( numberSpread[ nextY + 1 ][ nextX ] == counter ) {
					
					nextY++;
					continue;
				}
			}
			
			catch( ArrayIndexOutOfBoundsException e ) {
			}
			
			try {
				
				if( numberSpread[ nextY ][ nextX + 1 ] == counter ) {
					
					nextX++;
					continue;
				}
			}
			
			catch( ArrayIndexOutOfBoundsException e ) {
			}
			
			try {
				
				if( numberSpread[ nextY - 1 ][ nextX ] == counter ) {
					
					nextY--;
					continue;
				}
			}
			
			catch( ArrayIndexOutOfBoundsException e ) {
			}
		}
		
		Move moveHere = new Move( ID, nextX, nextY );
		
		return moveHere;	
	}
}